home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 147
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin
/
games
/
ippon
/
source.lzh
/
eshot.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-07-07
|
6KB
|
225 lines
/* eshot.c */
#include <stdio.h>
#include <xsp2lib.h>
#include "main.h"
#include "player.h"
#include "eshot.h"
#define PALET_ESHOT 0x0300
#define ESHOT_MAX 200 /* 敵弾最大数 */
static ESHOT eshot[ESHOT_MAX]; /* ワーク */
/* ゲーム開始時に呼ばれる */
void EshotInit (void)
{
int i;
/* リストをつなげる */
eshot_top = NULL;
eshot_null_top = eshot;
for (i = 0; i < ESHOT_MAX; i++)
eshot[i].next = &eshot[i + 1];
eshot[ESHOT_MAX - 1].next = NULL;
}
/* 敵弾出現時に呼ばれる */
void EshotAlloc (short type, signed short x, signed short y, unsigned char speed, unsigned char angle, signed short t)
{
ESHOT *p;
if (eshot_null_top == NULL) /* ワークの空きはあるか? */
return;
p = eshot_null_top;
eshot_null_top = p->next;
p->next = eshot_top;
eshot_top = p;
p->lx = (x - 8) << 16; /* (8,8) がスプライト座標の中心なので補正 */
p->ly = (y - 8) << 16;
p->vx = xytable[speed][angle].x;
p->vy = xytable[speed][angle].y;
if (t) { /* t フレーム後の値を初期値に */
p->lx += (p->vx * t);
p->ly += (p->vy * t);
}
/* メモ:敵弾の速度と当り判定の大きさについて */
/* eshot->hx が以下の場合、eshot->vx の最大値は以下の通り */
/* (hx,vx 未満) = (2,1.0),(3,3.0),(4,5.0),(5,7.0),(6,9.0) */
/* 算出式は以下の通り */
/* eshot->vx+player->vx > 2*eshot->hx の時判定抜けが発生 */
/* player->vx の最大値は 3.0(高速移動時) */
switch (p->type = type) {
case ESHOT_NRG01: /* エネルギー弾(極小) */
p->hit_p = 2; /* 速度を 1.0 未満にする事 */
p->pt = sp_eshot + type;
p->info = PALET_ESHOT | PRIORITY_ESHOT;
break;
case ESHOT_NRG02: /* 〃 (小) */
case ESHOT_NRG03: /* 〃 (中) */
case ESHOT_NRG04: /* 〃 (大) */
p->hit_p = 3; /* 速度を 3.0 未満にする事 */
p->pt = sp_eshot + type;
p->info = PALET_ESHOT | PRIORITY_ESHOT;
break;
case ESHOT_NRG05: /* 〃 (特大) */
case ESHOT_NRG06: /* 〃 (特大) */
case ESHOT_NRG22: /* 〃 (小横に2個) */
case ESHOT_NRG32: /* 〃 (中横に2個) */
case ESHOT_NRG23: /* 〃 (小3角形に3個) */
case ESHOT_NRG24: /* 〃 (小正方形に4個) */
case ESHOT_NRG14N: /* 〃 (小斜めに4個) */
case ESHOT_NRG24N: /* 〃 (中斜めに4個) */
case ESHOT_NRG34N: /* 〃 (中斜めに4個) */
case ESHOT_NRG34: /* 〃 (中正方形に4個) */
case ESHOT_NRG15: /* 〃 (小5個) */
case ESHOT_NRG35: /* 〃 (小と大正方形に5個) */
p->hit_p = 4; /* 速度を 5.0 未満にする事 */
p->pt = sp_eshot + type;
p->info = PALET_ESHOT | PRIORITY_ESHOT;
break;
#if 0
case ESHOT_LASER01:
p->hit_p = 3; /* 速度を 3.0 未満にする事 */
p->pt = sp_laser + 8;
p->info = PALET_ESHOT | PRIORITY_ESHOT;
break;
case ESHOT_LASEREX:
p->hit_p = 4; /* 速度を 5.0 未満にする事 */
p->pt = sp_laser + 9;
p->info = PALET_ESHOT | PRIORITY_ESHOT;
break;
#endif
default:
break;
}
}
/* 垂直同期ごとに呼ばれる */
void EshotMove (void)
{
ESHOT *p, *q;
signed short pl_x = player->x - 8, pl_y = player->y - 8;
#ifdef DEBUG
eshot_sum = 0;
#endif
p = eshot_top; /* 現在注目しているワーク */
q = NULL; /* 1つ前のワーク(ワーク削除時に必要) */
/* 弾消し中か?(高速化のためやや冗長なコードになってます) */
if (eshot_erase == 0) {
/* 通常の処理(弾消しではない) */
while (p != NULL) {
signed short p_x, p_y;
#ifdef DEBUG
eshot_sum++;
#endif
/* 速度を足して上位ワード(固定整数部)だけ取り出す */
p_x = p->x = (p->lx += p->vx) >> 16;
p_y = p->y = (p->ly += p->vy) >> 16;
/* 敵弾が画面外に出たか? */
/* (画面右から出た判定と左から出た判定を1回の比較で行っている) */
if (((unsigned short) p_x > 256 + 16) || ((unsigned short) p_y > 256 + 16)) {
/* 敵弾が画面外へ出たので消去 */
if (q == NULL) { /* リストの一番最初を削除 */
eshot_top = p->next;
p->next = eshot_null_top;
eshot_null_top = p;
q = NULL;
p = eshot_top;
} else {
q->next = p->next;
p->next = eshot_null_top;
eshot_null_top = p;
p = q->next;
}
} else {
/* 画面外へ出ていない時 */
/* 敵弾と自機の当たり判定 */
/* この辺の最適化は -fstrings-reduce が頑張ってくれるハズ */
signed short t, t2 = p->hit_p;
if (((t = p_y - t2) <= pl_y)
&& ((t += (short) (t2 << 1)) >= pl_y)
&& ((t = p_x + t2) >= pl_x)
&& ((t -= (short) (t2 << 1)) <= pl_x)) {
if ((player->status == PLAYER_STATUS_ALIVE) && (player->muteki == 0))
player->status = PLAYER_STATUS_DEAD;
} else {
xsp_set_st (p);
}
q = p;
p = p->next;
}
}
} else {
/* 弾消し中 */
char erase_flag; /* キャラクターを消す場合 =!0 */
unsigned short erase_table[14] =
{0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6};
while (p != NULL) {
signed short p_x, p_y;
if (eshot_erase > 1)
erase_flag = 0;
else
erase_flag = !0;
#ifdef DEBUG
eshot_sum++;
#endif
/* 速度を足して上位ワード(固定整数部)だけ取り出す */
p_x = p->x = (p->lx += p->vx) >> 16;
p_y = p->y = (p->ly += p->vy) >> 16;
/* 敵弾が画面外に出たか? */
/* (画面右から出た判定と左から出た判定を1回の比較で行っている) */
if (((unsigned short) p_x > 256 + 16) || ((unsigned short) p_y > 256 + 16))
erase_flag = !0;
if (erase_flag) {
/* 敵弾が画面外へ出たので消去 */
if (q == NULL) { /* リストの一番最初を削除 */
eshot_top = p->next;
p->next = eshot_null_top;
eshot_null_top = p;
q = NULL;
p = eshot_top;
} else {
q->next = p->next;
p->next = eshot_null_top;
eshot_null_top = p;
p = q->next;
}
} else {
p->pt = sp_eshotera + erase_table[eshot_erase];
xsp_set_st (p);
q = p;
p = p->next;
}
}
eshot_erase--;
}
}